import { query, difference, guID, isRegExp } from '@/common.js';
// 处理提示信息--------> 原先的提示函数：Message.info(`小数自动保留${value}位`)
const processTip = (function () {
  let lastId = 'zz';
  return function (el, msg) {
    if (query(`#${lastId}`)) {
      try {
        el.removeChild(query(`#${lastId}`));
      } catch (e) {
        console.log('鼠标移开');
      }
    }
    // el.parentNode.parentNode.classList.remove('ivu-form-item-error') // 移除组件的rule规则校验错误信息
    // if(query(`.ivu-form-item-error-tip`)) { el.parentNode.removeChild(query(`.ivu-form-item-error-tip`)) } // 删除爷爷的错误校验样式
    if (msg) {
      const id = 'z' + guID();
      let divObj = document.createElement('div'); // 创建，写内容
      divObj.id = id;
      divObj.innerHTML = `<div class="abs nowrap bgf zx1 r0 l0 tl fs12" style="bottom:-16px;color:#f56c6c;line-height:16px;height:16px;">${msg}</div>`;
      el.appendChild(divObj);
      lastId = id;
      setTimeout(() => {
        if (query(`#${id}`)) {
          el.removeChild(query(`#${id}`));
        }
      }, 2000);
    }
  };
})();
/**
 * 移除事件
 * @param {*} el
 */
function removeEvents(el) {
  el.inputRef.removeEventListener(
    'compositionstart',
    el.handleCompositionstart
  );
  el.inputRef.removeEventListener('compositionend', el.handlecompositionend);
  el.inputRef.removeEventListener('input', el.handleInput);
}
/**
 * 处理中文输入的情况
 * @param {*} ref 处理后的dom句柄
 * @param {*} el 当前绑定的dom
 * @param {*} vnode dom
 * @param {*} fn 处理函数
 */
function resolveChar(el, vnode) {
  el.handleCompositionstart = () => (vnode.inputLocking = true);
  el.handlecompositionend = () => {
    vnode.inputLocking = false;
    el.inputRef.dispatchEvent(new Event('input'));
  };
  el.inputRef.addEventListener('compositionstart', el.handleCompositionstart);
  el.inputRef.addEventListener('compositionend', el.handlecompositionend);
  el.inputRef.removeEventListener('input', el.handleInput);
  el.inputRef.addEventListener('input', el.handleInput, true);
}
/**
 * 允许输入什么
 * 允许中文：/[\u4e00-\u9fa5]/
 * 允许数字：/[0-9]/
 * 允许小写字母：/[a-z]/
 * 允许大写字母：/[A-Z]/
 * 允许下划线：_
 * 直接使用： <Input v-allow="[/[\u4e00-\u9fa5]/, /[0-9]/, /[a-z]/, /[A-Z]/, '_']"></Input>
 */
export const allow = {
  mounted(el, { value }, vnode) {
    const inputRef =
      el.querySelector('input') || el.querySelector('textarea') || el;
    el.inputRef = inputRef;
    el.handleInput = (e) =>
      window.requestAnimationFrame(() => {
        e.preventDefault();
        if (vnode.inputLocking) {
          return;
        }
        let originVal = inputRef.value;
        let tmp = inputRef.value;
        tmp = tmp
          .split('')
          .reduce(
            (prev, item) =>
              value.some((v) => (isRegExp(v) ? v.test(item) : v == item))
                ? prev + item
                : prev,
            ''
          );
        if (tmp != originVal) {
          processTip(
            el,
            `不符合规范的字符【${difference(
              originVal.split(''),
              tmp.split('')
            ).join(' ')}】，已经被过滤`
          );
        }
        inputRef.value = tmp;
        if (originVal != tmp) {
          inputRef.dispatchEvent(new Event('input'));
        }
      });
    resolveChar(el, vnode);
  },
  beforeUnmount(el) {
    removeEvents(el);
  },
};
/**
 * 禁止输入什么
 * 禁止中文：/[\u4e00-\u9fa5]/
 * 禁止数字：/[0-9]/
 * 禁止小写字母：/[a-z]/
 * 禁止大写字母：/[A-Z]/
 * 禁止下划线：_
 * 直接使用： <Input v-ban="[/[\u4e00-\u9fa5]/, /[0-9]/, /[a-z]/, /[A-Z]/, '_']"></Input>
 */
export const ban = {
  mounted(el, { value }, vnode) {
    const inputRef =
      el.querySelector('input') || el.querySelector('textarea') || el;
    el.inputRef = inputRef;
    el.handleInput = (e) =>
      window.requestAnimationFrame(() => {
        e.preventDefault();
        if (vnode.inputLocking) {
          return;
        }
        let originVal = inputRef.value;
        let tmp = inputRef.value;
        tmp = tmp
          .split('')
          .reduce(
            (prev, item) =>
              value.some((v) => (isRegExp(v) ? v.test(item) : v == item))
                ? prev
                : prev + item,
            ''
          );
        if (tmp != originVal) {
          processTip(
            el,
            `不符合规范的字符【${difference(
              originVal.split(''),
              tmp.split('')
            ).join(' ')}】，已经被过滤`
          );
        }
        inputRef.value = tmp;
        if (originVal != tmp) {
          inputRef.dispatchEvent(new Event('input'));
        }
      });
    resolveChar(el, vnode);
  },
  beforeUnmount(el) {
    removeEvents(el);
  },
};
/**
 * 首字符删除什么
 * @param {Function}
 * 删除中文：/[\u4e00-\u9fa5]/
 * 删除数字：/[0-9]/
 * 删除小写字母：/[a-z]/
 * 删除大写字母：/[A-Z]/
 * 删除下划线：_
 * 直接使用： <Input v-cutHead="[/[0-9]/]"></Input>
 */
export const cutHead = {
  mounted(el, { value }, vnode) {
    const inputRef =
      el.querySelector('input') || el.querySelector('textarea') || el;
    el.inputRef = inputRef;
    el.handleInput = (e) =>
      window.requestAnimationFrame(() => {
        e.preventDefault();
        if (vnode.inputLocking) {
          return;
        }
        let originVal = inputRef.value;
        let tmp = inputRef.value;
        const [left, right] = [tmp[0], tmp.slice(1)];
        tmp = value.some((v) => (isRegExp(v) ? v.test(left) : v == left))
          ? right
          : tmp;
        if (tmp != originVal) {
          processTip(
            el,
            `不能用【${difference(originVal.split(''), tmp.split('')).join(
              ' '
            )}】开头`
          );
        }
        inputRef.value = tmp;
        if (originVal != tmp) {
          inputRef.dispatchEvent(new Event('input'));
        }
      });
    resolveChar(el, vnode);
  },
  beforeUnmount(el) {
    removeEvents(el);
  },
};
/**
 * 编码格式大小写字母、数字、英文符号
 * @param {Function}
 * 直接使用： <Input v-code></Input>
 */
export const code = {
  mounted(el, { value }, vnode) {
    const inputRef = el.querySelector('input') || el;
    el.inputRef = inputRef;
    el.handleInput = (e) =>
      window.requestAnimationFrame(() => {
        e.preventDefault();
        if (vnode.inputLocking) {
          return;
        }
        let originVal = inputRef.value;
        let tmp = inputRef.value;
        tmp = tmp.replace(/[^0-9A-Za-z!@#$%^&*()_+-{}?><|/.,`]/g, '');
        if (tmp != originVal) {
          processTip(
            el,
            `不符合规范的字符【${difference(
              originVal.split(''),
              tmp.split('')
            ).join(' ')}】，已经被过滤`
          );
        }
        inputRef.value = tmp;
        if (originVal != tmp) {
          inputRef.dispatchEvent(new Event('input'));
        }
      });
    resolveChar(el, vnode);
  },
  beforeUnmount(el) {
    removeEvents(el);
  },
};
/**
 * 编码格式大小写字母、数字、英文符号
 * @param {Function}
 * 直接使用： <Input v-type></Input>
 */
export const type = {
  mounted(el, { value }, vnode) {
    const inputRef = el.querySelector('input') || el;
    el.inputRef = inputRef;
    el.handleInput = (e) =>
      window.requestAnimationFrame(() => {
        e.preventDefault();
        if (vnode.inputLocking) {
          return;
        }
        let originVal = inputRef.value;
        let tmp = inputRef.value;
        tmp = tmp.replace(/[^0-9A-Za-z_-\s]/g, '');
        if (tmp != originVal) {
          processTip(
            el,
            `不符合规范的字符【${difference(
              originVal.split(''),
              tmp.split('')
            ).join(' ')}】，已经被过滤`
          );
        }
        inputRef.value = tmp;
        if (originVal != tmp) {
          inputRef.dispatchEvent(new Event('input'));
        }
      });
    resolveChar(el, vnode);
  },
  beforeUnmount(el) {
    removeEvents(el);
  },
};
/**
 * 数据集名称
 * @param {Function}
 * 直接使用： <Input v-dataSet></Input>
 */
export const dataSet = {
  mounted(el, { value }, vnode) {
    const inputRef = el.querySelector('input') || el;
    el.inputRef = inputRef;
    el.handleInput = (e) =>
      window.requestAnimationFrame(() => {
        e.preventDefault();
        if (vnode.inputLocking) {
          return;
        }
        let originVal = inputRef.value;
        let tmp = inputRef.value;
        tmp = tmp.replace(/[^a-zA-Z0-9_]/g, '');
        if (tmp != originVal) {
          processTip(
            el,
            `不符合规范的字符【${difference(
              originVal.split(''),
              tmp.split('')
            ).join(' ')}】，已经被过滤`
          );
        }
        inputRef.value = tmp;
        if (originVal != tmp) {
          inputRef.dispatchEvent(new Event('input'));
        }
      });
    resolveChar(el, vnode);
  },
  beforeUnmount(el) {
    removeEvents(el);
  },
};
/**
 * 标签名称
 * @param {Function}
 * 直接使用： <Input v-tag></Input>
 */
export const tag = {
  mounted(el, { value }, vnode) {
    const inputRef =
      el.querySelector('input') || el.querySelector('textarea') || el;
    el.inputRef = inputRef;
    el.handleInput = (e) =>
      window.requestAnimationFrame(() => {
        e.preventDefault();
        if (vnode.inputLocking) {
          return;
        }
        let originVal = inputRef.value;
        let tmp = inputRef.value;
        tmp = tmp.replace(
          /[!@#$%^&*()+{}?><|/.,`！￥……（）=——\[\]；‘’。，、]/g,
          ''
        );
        if (tmp != originVal) {
          processTip(
            el,
            `不符合规范的字符【${difference(
              originVal.split(''),
              tmp.split('')
            ).join(' ')}】，已经被过滤`
          );
        }
        inputRef.value = tmp;
        if (originVal != tmp) {
          inputRef.dispatchEvent(new Event('input'));
        }
      });
    resolveChar(el, vnode);
  },
  beforeUnmount(el) {
    removeEvents(el);
  },
};
/**
 * 限制整数
 * @param {Function}
 * 直接使用： <Input v-int></Input>
 * 传入true，允许输入负值： <Input v-int="true"></Input>
 */
export const int = {
  mounted(el, { value }, vnode) {
    const inputRef = el.querySelector('input') || el;
    el.inputRef = inputRef;
    el.handleInput = (e) =>
      window.requestAnimationFrame(() => {
        e.preventDefault();
        if (vnode.inputLocking) {
          return;
        }
        let originVal = inputRef.value;
        let tmp = inputRef.value.replace(
          eval(`/[^0-9${value ? '-' : ''}]/g`),
          ''
        );
        const symbol = tmp.at(0) == '-' ? '-' : '';
        if (symbol === '-') {
          tmp = tmp.slice(1);
        }
        tmp = tmp.replace(/-/g, '');
        tmp = tmp == '' ? '' : tmp.replace(/^0+/g, '') || '0';
        tmp = symbol + tmp;
        if (tmp != originVal) {
          processTip(
            el,
            `不符合规范的字符【${difference(
              originVal.split(''),
              tmp.split('')
            ).join(' ')}】，已经被过滤`
          );
        }
        inputRef.value = tmp;
        if (originVal != tmp) {
          inputRef.dispatchEvent(new Event('input'));
        }
      });
    resolveChar(el, vnode);
  },
  beforeUnmount(el) {
    removeEvents(el);
  },
};
/**
 * 限制只能输入小数
 * @param {Function}
 * 直接使用： <Input v-float></Input>
 * 传入true使用，允许输入负值： <Input v-float="true"></Input>
 */
export const float = {
  mounted(el, { value }, vnode) {
    let inputRef = el.querySelector('input') || el;
    el.inputRef = inputRef;
    el.handleInput = (e) =>
      window.requestAnimationFrame(() => {
        e.preventDefault();
        if (vnode.inputLocking) {
          return;
        }
        let originVal = inputRef.value;
        let tmp = inputRef.value;
        // console.log(tmp)
        tmp = tmp.replace(eval(`/[^0-9.${value ? '-' : ''}]/g`), ''); // 非数字、点、负号，替换为空
        if (tmp != originVal) {
          processTip(
            el,
            `不符合规范的字符【${difference(
              originVal.split(''),
              tmp.split('')
            ).join(' ')}】，已经被过滤`
          );
        }
        const symbol = tmp.at(0) == '-' ? '-' : '';
        if (symbol === '-') {
          tmp = tmp.slice(1);
        }
        tmp = tmp.replace(/-/g, '');
        tmp = tmp.split('').reduce(
          (prev, item) => {
            if (item === '.') {
              prev.tmp += prev.dotNum === 0 ? item : '';
              prev.dotNum++;
            } else {
              prev.tmp += item;
            }
            return prev;
          },
          { tmp: '', dotNum: 0 }
        )['tmp'];
        if (tmp.includes('.') && /-?([0-9]*).([0-9]*)/.test(tmp)) {
          const [, left, right] = tmp.match(/-?([0-9]*).([0-9]*)/);
          tmp = symbol + (left.replace(/^[0]+/g, '') || '0') + '.' + right;
        } else {
          tmp = symbol + (tmp == '' ? '' : tmp.replace(/^[0]+/, '') || '0');
        }
        // if(tmp && !['-', '.', '0', ''].includes(tmp.at(-1))) {
        //   if(round(tmp, value || 0) != tmp) { Message.info(`四舍五入，保留${value}位小数，多余的数据被过滤`) }
        //   tmp = round(tmp, value || 0)
        // }
        inputRef.value = tmp;
        if (originVal != tmp) {
          inputRef.dispatchEvent(new Event('input'));
        }
      });
    if (!inputRef) {
      inputRef = el;
    }
    resolveChar(el, vnode);
  },
  beforeUnmount(el) {
    removeEvents(el);
  },
};
/**
 * 字段名格式，只能由数字、字母、下划线构成，并且不能以数字开头
 * @param {Function}
 * 直接使用： <Input v-field></Input>
 */
export const field = {
  mounted(el, { value }, vnode) {
    const inputRef = el.querySelector('input') || el;
    el.inputRef = inputRef;
    el.handleInput = (e) =>
      window.requestAnimationFrame(() => {
        e.preventDefault();
        if (vnode.inputLocking) {
          return;
        }
        let originVal = inputRef.value;
        let tmp = inputRef.value;
        tmp = tmp.replace(/[^0-9A-Za-z_]/g, '');
        let testTmp0 = tmp[0];
        while (/[0-9]/.test(tmp[0])) {
          tmp = tmp.slice(1);
        }
        inputRef.value = tmp;
        if (originVal != tmp) {
          if (/[0-9]/.test(testTmp0)) {
            processTip(
              el,
              `不能以数字开头，不合规范的字符【${difference(
                originVal.split(''),
                tmp.split('')
              ).join(' ')}】，已经被过滤`
            );
          } else {
            processTip(
              el,
              `只能由数字、字母、下划线构成，不合规范的字符【${difference(
                originVal.split(''),
                tmp.split('')
              ).join(' ')}】，已经被过滤`
            );
          }
          inputRef.dispatchEvent(new Event('input'));
        }
      });
    resolveChar(el, vnode);
  },
  beforeUnmount(el) {
    removeEvents(el);
  },
};
/**
 * 姓名，不可以输入空格和数字
 * @param {Function}
 * 直接使用： <Input v-name></Input>
 */
export const name = {
  mounted(el, { value }, vnode) {
    const inputRef = el.querySelector('input') || el;
    el.inputRef = inputRef;
    el.handleInput = (e) =>
      window.requestAnimationFrame(() => {
        e.preventDefault();
        if (vnode.inputLocking) {
          return;
        }
        let originVal = inputRef.value;
        let tmp = inputRef.value;
        tmp = tmp.replace(/[0-9!@#$%^&*()_+-?><|/,`！，、？~\s]+/g, '');
        inputRef.value = tmp;
        if (originVal != tmp) {
          processTip(
            el,
            `不符合规范的字符【${difference(
              originVal.split(''),
              tmp.split('')
            ).join(' ')}】，已经被过滤`
          );
        }
        if (originVal != tmp) {
          inputRef.dispatchEvent(new Event('input'));
        }
      });
    resolveChar(el, vnode);
  },
  beforeUnmount(el) {
    removeEvents(el);
  },
};
/**
 * 去除空格
 * @param {Function}
 * 直接使用，去除首尾空格： <Input v-trim></Input>
 * 传入0，去除首尾空格： <Input v-trim="'headTail'"></Input>
 * 传入1，去除全部空格： <Input v-trim="'all'"></Input>
 * 传入2，去除头部空格： <Input v-trim="'head'"></Input>
 * 传入3，去除尾部空格： <Input v-trim="'tail'"></Input>
 */
export const trim = {
  mounted(el, { value }, vnode) {
    const inputRef = el.querySelector('input') || el;
    el.inputRef = inputRef;
    el.handleInput = (e) =>
      window.requestAnimationFrame(() => {
        e.preventDefault();
        if (vnode.inputLocking) {
          return;
        }
        let originVal = inputRef.value;
        let tmp = inputRef.value;
        const reg = {
          headTail: new RegExp(/(^\s*)|(\s*$)/g),
          all: new RegExp(/\s+/g),
          head: new RegExp(/(^\s*)/g),
          tail: new RegExp(/(\s*$)/g),
        };
        value = value || 'headTail'
        tmp = tmp.replace(reg[value], '');
        inputRef.value = tmp;
        if (originVal != tmp) {
          processTip(el, `空格已被过滤`);
        }
        if (originVal != tmp) {
          inputRef.dispatchEvent(new Event('input'));
        }
      });
    resolveChar(el, vnode);
  },
  beforeUnmount(el) {
    removeEvents(el);
  },
};
/**
 * 限制最多输入几个字符
 * @param {Function}
 * 直接使用： <Input v-limit="[0,5]"></Input>
 */
export const limit = {
  mounted(el, { value }, vnode) {
    const inputRef =
      el.querySelector('input') || el.querySelector('textarea') || el;
    el.inputRef = inputRef;
    el.handleInput = (e) =>
      window.requestAnimationFrame(() => {
        e.preventDefault();
        if (vnode.inputLocking) {
          return;
        }
        let originVal = inputRef.value;
        let tmp = inputRef.value;
        const [min, max] = value;
        tmp = tmp.slice(0, Number(max));
        inputRef.value = tmp;
        if (originVal != tmp) {
          processTip(el, `最多输入${max}个字符`);
        }
        if (originVal.length < Number(min)) {
          processTip(el, `最少输入${min}个字符`);
        }
        if (originVal != tmp) {
          inputRef.dispatchEvent(new Event('input'));
        }
      });
    resolveChar(el, vnode);
  },
  beforeUnmount(el) {
    removeEvents(el);
  },
};
/**
 * 限制小数点后保留几位
 * @param {Function}
 * 直接使用： <Input v-decimalLimit="2"></Input>
 */
export const decimalLimit = {
  mounted(el, { value }, vnode) {
    const inputRef = el.querySelector('input') || el;
    el.inputRef = inputRef;
    el.handleInput = (e) =>
      window.requestAnimationFrame(() => {
        e.preventDefault();
        if (vnode.inputLocking) {
          return;
        }
        let originVal = inputRef.value;
        let tmp = inputRef.value;
        if (tmp.includes('.') && /-?([0-9]*).([0-9]*)/.test(tmp)) {
          const [, left, right] = tmp.match(/-?([0-9]*).([0-9]*)/);
          if (right.length > value) {
            tmp = left
              ? (tmp.at(0) == '-' ? '-' : '') +
                left +
                '.' +
                right.slice(0, Number(value))
              : '';
          }
          inputRef.value = tmp;
        }
        if (originVal != tmp) {
          processTip(el, `小数自动保留${value}位`);
        }
        if (originVal != tmp) {
          inputRef.dispatchEvent(new Event('input'));
        }
      });
    resolveChar(el, vnode);
  },
  beforeUnmount(el) {
    removeEvents(el);
  },
};
/**
 * 限制最小值
 * @param {Function}
 * 直接使用： <Input v-min="0"></Input>
 */
export const min = {
  mounted(el, { value }, vnode) {
    const inputRef = el.querySelector('input') || el;
    el.inputRef = inputRef;
    el.handleInput = (e) =>
      window.requestAnimationFrame(() => {
        e.preventDefault();
        if (vnode.inputLocking) {
          return;
        }
        let originVal = inputRef.value;
        let tmp = inputRef.value;
        if (tmp && Number(tmp) < Number(value)) {
          tmp = value;
          processTip(el, `最小值为${value}`);
        }
        inputRef.value = tmp;
        if (originVal != tmp) {
          inputRef.dispatchEvent(new Event('input'));
        }
      });
    resolveChar(el, vnode);
  },
  beforeUnmount(el) {
    removeEvents(el);
  },
};
/**
 * 限制最大值
 * @param {Function}
 * 直接使用： <Input v-max="100"></Input>
 */
export const max = {
  mounted(el, { value }, vnode) {
    const inputRef = el.querySelector('input') || el;
    el.inputRef = inputRef;
    el.handleInput = (e) =>
      window.requestAnimationFrame(() => {
        e.preventDefault();
        if (vnode.inputLocking) {
          return;
        }
        let originVal = inputRef.value;
        let tmp = inputRef.value;
        if (tmp && Number(tmp) > Number(value)) {
          tmp = value;
          processTip(el, `最大值为${value}`);
        }
        inputRef.value = tmp;
        if (originVal != tmp) {
          inputRef.dispatchEvent(new Event('input'));
        }
      });
    resolveChar(el, vnode);
  },
  beforeUnmount(el) {
    removeEvents(el);
  },
};
/**
 * input遮罩层，禁止选择
 * @param {Function}
 * 直接使用： <Input v-model="accountObj._pwd" @on-change="inputPwd" type="text" v-mask placeholder="请输入登录密码"></Input>
 */
export const mask = {
  mounted(el, { value }, vnode) {
    const inputRef = el.querySelector('input') || el;
    const fatherDom = inputRef.parentElement;
    fatherDom.style.position = 'relative';
    const op10Mask = document.createElement('div');
    op10Mask.style.backgroundColor = 'transparent';
    op10Mask.style.position = 'absolute';
    op10Mask.style.top = '0';
    op10Mask.style.right = '0';
    op10Mask.style.bottom = '0';
    op10Mask.style.left = '0';
    el.handler = () => {
      inputRef.focus && inputRef.focus();
    };
    op10Mask.addEventListener('click', el.handler);
    fatherDom.appendChild(op10Mask);
  },
  beforeUnmount(el) {
    el.inputRef.removeEventListener('click', el.handler);
  },
};
/**
 * input自动聚焦指令
 * @param {Function}
 * 直接使用： <Input v-focus></Input>
 */
export const focus = {
  mounted: function (el) {
    // 聚焦元素
    const inputRef = el.querySelector('input');
    inputRef ? inputRef.focus() : el.focus();
  },
};
